PostgreSQL 全文搜索 查询解析函数
1 背景知识
PostgreSQL提供了以下函数,将一个查询转换成 tsquery
数据类型。
to_tsquery
plainto_tsquery
phraseto_tsquery
websearch_to_tsquery
1.1 to_tsquery
to_tsquery
提供了比 plainto_tsquery
和 phraseto_tsquery
更多的特性,但是它对其输入要求更加严格。
1.2 websearch_to_tsquery
websearch_to_tsquery
是 to_tsquery
的一个简化版本,类似于Web搜索引擎使用的语法。
2 to_tsquery
to_tsquery
函数从 querytext
创建一个 tsquery
值。querytext
由操作符 &(AND)、|(OR)、!(NOT)、<->(FOLLOWED BY)和单词
组成。
2.1 语法定义
to_tsquery([ config regconfig, ] querytext text) returns tsquery
对于 tsquery 。to_tsquery
把每一个 记号
正规化成一个 词位
,并且丢弃掉任何是停用词的 记号
。一个具体的例子如下:
SELECT to_tsquery('english', 'The & Fat & Rats');
to_tsquery
---------------
'fat' & 'rat'
(1 row)
2.2 权重标签
每一个词位可以添加tsquery 权重,用于限制匹配权重一致的 tsvector
词位。例如:Rats 需要再标题出现,也需要在正文中出现。
SELECT to_tsquery('Doors:AB & Woman:A');
to_tsquery
-----------------------
'door':AB & 'woman':A
(1 row)
例子
SELECT film_id,title,description
FROM film
WHERE fulltext @@ to_tsquery('DOOR:AB & Woman:A');
2.3 匹配标签 *
SELECT to_tsquery('english','Doors:* & Woman:*');
to_tsquery
----------------------
'door':* & 'woman':*
(1 row)
例子
SELECT film_id,title,description
FROM film
WHERE fulltext @@ to_tsquery('DOOR:* & Woman:*');
-[ RECORD 1 ]---------------------------
film_id | 584
title | MIXED DOORS
description | A Taut Drama of a Womanizer And a Lumberjack who must Succumb a Pioneer in Ancient India
-[ RECORD 2 ]-----------------------------
film_id | 243
title | DOORS PRESIDENT
description | A Awe-Inspiring Display of a Squirrel And a Woman who must Overcome a Boy in The Gulf of Mexico
2.4 短语句标签
to_tsquery 函数也能够传入段语句。根据标准词典将 supernovae
正规化为 supernova
,也将 stars
正规化为 star
。
SELECT to_tsquery('''supernovae stars'' & !crab');
to_tsquery
----------------------------------
'supernova' <-> 'star' & !'crab'
(1 row)
3 plainto_tsquery
3.1 语法定义
plainto_tsquery([ config regconfig, ] querytext text) returns tsquery
3.2 未格式化的文本
将未格式化的文本 querytext
转换成一个 tsquery
值。然后插入 &
(AND)布尔操作符词词位之间。
SELECT plainto_tsquery('english', 'The Fat Rats');
//屏幕输出:
plainto_tsquery
-----------------
'fat' & 'rat'
(1 row)
3.3 忽略其他的符号
注意: plainto_tsquery
不会识别 tsquery
操作符、权重标签
或 匹配标签
:
这里,所有的的符号将被丢弃。
SELECT plainto_tsquery('english', 'The Fat & Rats:C');
//屏幕输出:
plainto_tsquery
---------------------
'fat' & 'rat' & 'c'
3.4 plainto_tsquery 与 to_tsquery 区别
to_tsquery
传入 '''xxxxx'''
字符串形式。而 plainto_tsquery
只需要传入 'xxx'
字符串形式。
testdb=# SELECT to_tsquery('english', '''The Fat Rats''');
//屏幕输出:
to_tsquery
-----------------
'fat' <-> 'rat'
(1 row)
4 phraseto_tsquery
phraseto_tsquery
与 plainto_tsquery
相似。但是还是有细微差别。
phraseto_tsquery
会插入<->(FOLLOWED BY)
操作符,而plainto_tsquery
会插入& (AND)
操作符。- 停用词通过插入
<N>
操作符,而不是<->
操作符。在搜索准确的词位位置时这个函数很有用,因为 FOLLOWED BY 操作符不只是检查所有词位的存在性,还会检查词位的顺序。
4.1 语法定义
phraseto_tsquery([ config regconfig, ] querytext text) returns tsquery
4.2 未格式化的文本
SELECT phraseto_tsquery('english', 'The Fat Rats');
//屏幕输出:
phraseto_tsquery
------------------
'fat' <-> 'rat'
4.3 忽略其他的符号
和 plainto_tsquery
相似,phraseto_tsquery
会丢弃 tsquery
操作符、权重标签
或 匹配标签
:
SELECT phraseto_tsquery('english', 'The Fat & Rats:C');
//屏幕输出:
phraseto_tsquery
-----------------------------
'fat' <-> 'rat' <-> 'c'
5 websearch_to_tsquery
websearch_to_tsquery
可以从未格式化文本 querytext
创建一个 tsquery
值。和 plainto_tsquery
以及 phraseto_tsquery
函数不同,它可以识别特定的操作符。此外,这个函数不会报出语法错误,这就可以把原始的用户提供的输入用于搜索。
5.1 语法定义
websearch_to_tsquery([ config regconfig, ] querytext text) returns tsquery
支持下列语法:
5.2 无引号文本
文本将将转换成由 &
操作符分隔的词位,类似 plainto_tsquery
函数。
SELECT websearch_to_tsquery('english', 'The fat rats');
//屏幕输出:
websearch_to_tsquery
----------------------
'fat' & 'rat'
(1 row)
5.3 引号文本
文本将被转换成由 <->
操作符分隔的词,就像被类似 phraseto_tsquery
函数。
SELECT websearch_to_tsquery('english', '"supernovae stars" -crab');
//屏幕输出:
websearch_to_tsquery
----------------------------------
'supernova' <-> 'star' & !'crab'
(1 row)
5.4 OR
如果文本中包含“or”,将转换为 |
运算符。
websearch_to_tsquery
-----------------------------------
'sad' <-> 'cat' | 'fat' <-> 'rat'
(1 row)
5.5 破折号(-)
破折号将转换为 !
运算符。
SELECT websearch_to_tsquery('english', 'signal -"segmentation fault"');
websearch_to_tsquery
---------------------------------------
'signal' & !( 'segment' <-> 'fault' )
(1 row)
5.6 忽略其他的符号
- 与
plainto_tsquery
和phraseto_tsquery
一样,websearch_to_tsquery
函数将不会识别tsquery
运算符、权重标签
或匹配标签
。
SELECT websearch_to_tsquery('english', '""" )( dummy \\ query <->');
//屏幕输出:
websearch_to_tsquery
----------------------
'dummi' & 'queri'
(1 row)